package com.paradogs.framework.server;

import com.paradogs.common.utils.CfgUtils;
import com.paradogs.common.utils.EventUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @author: yumi
 * @date: 2023/12/27  9:39
 * @Description: websocket 服务器
 */
@Slf4j
@Component
public class ParadogsWSServer implements ApplicationRunner {

    @Value("${server.uuid")
    private String uuid;

    @Value("${server.ws}")
    private String wsRoute;

    @Value("${server.port}")
    private int port;

    public void start(int port) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new HttpServerCodec());
                            pipeline.addLast(new HttpObjectAggregator(65536));
                            pipeline.addLast(new ChunkedWriteHandler());
                            pipeline.addLast(new WebSocketServerProtocolHandler(wsRoute));
                            pipeline.addLast(new ParadogsWSMessageHandler());
                        }
                    });

            ParadogsServerHolder.server = b.bind(port).sync().channel();
            log.info("Server start on {}, ws: {}", port, wsRoute);
            System.out.println(" ________  ________  ________  ________  ________  ________  ________  ________      \n" +
                    "|\\   __  \\|\\   __  \\|\\   __  \\|\\   __  \\|\\   ___ \\|\\   __  \\|\\   ____\\|\\   ____\\     \n" +
                    "\\ \\  \\|\\  \\ \\  \\|\\  \\ \\  \\|\\  \\ \\  \\|\\  \\ \\  \\_|\\ \\ \\  \\|\\  \\ \\  \\___|\\ \\  \\___|_    \n" +
                    " \\ \\   ____\\ \\   __  \\ \\   _  _\\ \\   __  \\ \\  \\ \\\\ \\ \\  \\\\\\  \\ \\  \\  __\\ \\_____  \\   \n" +
                    "  \\ \\  \\___|\\ \\  \\ \\  \\ \\  \\\\  \\\\ \\  \\ \\  \\ \\  \\_\\\\ \\ \\  \\\\\\  \\ \\  \\|\\  \\|____|\\  \\  \n" +
                    "   \\ \\__\\    \\ \\__\\ \\__\\ \\__\\\\ _\\\\ \\__\\ \\__\\ \\_______\\ \\_______\\ \\_______\\____\\_\\  \\ \n" +
                    "    \\|__|     \\|__|\\|__|\\|__|\\|__|\\|__|\\|__|\\|_______|\\|_______|\\|_______|\\_________\\\n" +
                    "                                                                         \\|_________|\n" +
                    "                                                                                     \n" +
                    "                                                                                     ");
            ParadogsServerHolder.server.closeFuture().sync();
            log.info("Server stop...");

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
//            log.info("NIO group shutdown gracefully");
        }
    }

    @Async
    @Override
    public void run(ApplicationArguments args) throws Exception {
        start(port);
    }

}
